/*!
 *  \file       test-fft.cpp
 *  \brief      Main per testare se la FFT coincide con la DFT
 *
 * Questo programma testa se la FFT generata dal segnale passato da commandline
 * coincide con la DFT teorica
 *
 *  \author     Davide Scola <S2299453@studenti.unige.it>
 *  \author		Minetti Alberto <S3064777@studenti.unige.it>
 *  \version    1.0
 *
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <cmath>
#include <limits>
#include <vector>
#include <iostream>
#include "ISignalGenerator.hpp"	
#include "StaircaseSignalGenerator.cpp"
#include "InputSignal.cpp"
#include "WrapNumber.cpp"
#include "RealNumber.hpp"
#include "Fft.cpp"


using namespace std;

/*!
 *  \brief      	Calcolo della DFT
 *
 *	Questa funzione calcola la DFT.
 *
 *  \param[in]		input	il segnale in input
 *  \param[out]		dft		la dft calcolata
 *
 */
template< typename tType > void
theoricDFT( const InputSignal< tType > input, vector< tType >& dft )
{
    int nComponents = input.nonZeroElements( );
    long double epsilon = numeric_limits< long double >::epsilon( );
    
    dft[ 0 ] =  tType( sin( M_PI / dft.size() * nComponents * epsilon ) / 
                        sin( M_PI / dft.size() * epsilon ) );
    
    for( unsigned long int iCount = 1; iCount < dft.size(); ++iCount )
    {
        dft[ iCount ] =  tType( sin( M_PI / dft.size() * nComponents * iCount ) /
                                sin( M_PI / dft.size() * iCount ) );
    }
}


int
main( int argc, char *argv[] )
{
    int retValue = 0;
    bool beVerbose = false;
    
    Fft< RealNumber > fft( INPUT_SIZE );
    vector< RealNumber > th_dft( INPUT_SIZE );
    
    if( argc > 1 && string( argv[1] ) == string( "-v" ) ) {
        beVerbose = true;
        --argc; ++argv;
    }
    
    StaircaseSignalGenerator< RealNumber > generator( --argc, ++argv );
    InputSignal< RealNumber > input( INPUT_SIZE, generator );
    
    theoricDFT( input, th_dft );
    fft.compute( input );
    
    cout.precision( 12 );
    
    for( unsigned int i = 0; i < fft.size() && i < th_dft.size(); i++ ) {
        if( beVerbose ) {
            cout << i << " " << fft[i].real() << " " << th_dft[i] << endl;
        }
        
        if( fft[i] != th_dft[i] ) {
            retValue = 1;
        }
    }
    
    return retValue;
}
